home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 10
/
AACD 10.iso
/
AACD
/
Games
/
MAME
/
src
/
gfxobj.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-03
|
11KB
|
398 lines
/*
gfx object manager
Games currently using the Sprite Manager:
Namco System1
Graphic Object Manager controls all Graphic object and the priority.
The thing to draw in tile of gfx element by an arbitrary size can be done.
That is, it is useful for the sprite system which shares a different size.
The drawing routine can be replaced with callbacking user routine.
The control of priority becomes easy if tilemap draws by using this function.
If gfx like special drawing routine is made,complexity overlapping sprite can be include.
Currently supported features include:
- The position and the size can be arbitrarily specified from gfx tile.
( It is achieved by using clipping.)
- priority ordering.
- resource tracking (gfxobj_init and gfxobj_close must be called by mame.c)
- offscreen object skipping
Schedule for the future
- zoomming gfx with selectable tile position and size
- palette usage tracking
- uniting with Sprite Manager
- priority link system in object list.
Hint:
-The position and the size select :
This is similar to SPRITE_TYPE_UNPACK of Sprite Manager.
(see also comments in sprite.c.)
objects->top
objects->left -> The display beginning position in gfx tile is specified.
objects->width
objects->height -> The display size is specified.
Gfx object manager adjust the draw position from the value of top and left.
And,the clipping position is adjusted according to the size.
-The palette resource tracking :
sprite manager it not supported yet.
User should control palette resource for yourself.
If you use sort mode,the object not seen has exclusion from the object link.
Therefore, examining objectlink will decrease the overhead.
example:
gfxobj_update();
if(object=objectlist->first_object ; object != 0 ; object=object->next)
{
color = object->color;
mark_palette_used_flag(color);
}
-Priority order
Gfx object manager can sort the object by priority.
The condition of sorting is decided by the flag.
gfxobject_list->sort_type;
GFXOBJ_DONT_SORT:
Sorting is not done.
The user should be build object link list.
excluded objects from link are not updated.
gfxobject_list->first_object; -> first object point (lower object)
gfxobject->next -> next object point ,0 = end of link(higher)
GFXOBJ_DOT_SORT:
Sorting is done.
The condition by object->priority is given to priority most.
object->priority = p -> p=0 : lower , p=object_list->max_priority-1 : higher
If 'GFXOBJ_SORT_PRIORITY_BACK' is specified, order is reversed.
Next, the array of object is given to priority.
object_list->objects[x] -> x=0 : lower , x=object_list->nums-1 = higher
If 'GFXOBJ_SORT_OBJECT_BACK' is specified, order is reversed.
-The handling of tilemap :
Tilemap can be treated by the callback function as one object.
If the user function is registered in object->special_handler,
the user function is called instead of drawgfx.
Call tilemap_draw() in your callback handler.
If object->code is numbered with two or more tilemap,it might be good.
If you adjust objects->gfx to 0,Useless processing to tilemap is omitted.
clipping,drawposition,visible,dirty_flag are not updated.
If one tilemap is displayed with background and foreground
Use two objects behind in front of sprite.
Example:
object resource:
objects[0] == tilemap1 , higher background
objects[1] == tilemap2 , lower background
objects[3] == lower sprite
objects[4] == middle sprite
objects[5] == higher sprite
objects[2] == tilemap2 , foreground
objects[0].code = 1; number of tilemap_2
objects[0].color = 0; background mark
objects[1].code = 0; number of tilemap_1
objects[1].color = 0; background mark
objects[5].code = 0; number of tilemap_1
objects[5].color = 1; foreground mark
objects[0,1,5].special_handler = object_draw_tile;
objects[0,1,5].gfx = 0;
callback handler:
void object_draw_tile(struct osd_bitmap *bitmap,struct gfx_object *object)
{
tilemap_draw( bitmap , tilemap[object->code] , object->color );
}
*/
#include "driver.h"
/* #include "gfxobj.h" */
static struct gfx_object_list *first_object_list;
void gfxobj_init(void)
{
first_object_list = 0;
}
void gfxobj_close(void)
{
struct gfx_object_list *object_list,*object_next;
for(object_list = first_object_list ; object_list != 0 ; object_list=object_next)
{
free(object_list->objects);
object_next = object_list->next;
free(object_list);
}
}
#define MAX_PRIORITY 16
struct gfx_object_list *gfxobj_create(int nums,int max_priority,const struct gfx_object *def_object)
{
struct gfx_object_list *object_list;
int i;
/* priority limit check */
if(max_priority >= MAX_PRIORITY)
return 0;
/* allocate object liset */
if( (object_list = malloc(sizeof(struct gfx_object_list))) == 0 )
return 0;
memset(object_list,0,sizeof(struct gfx_object_list));
/* allocate objects */
if( (object_list->objects = malloc(nums*sizeof(struct gfx_object))) == 0)
{
free(object_list);
return 0;
}
if(def_object == 0)
{ /* clear all objects */
memset(object_list->objects,0,nums*sizeof(struct gfx_object));
}
else
{ /* preset with default objects */
for(i=0;i<nums;i++)
memcpy(&object_list->objects[i],def_object,sizeof(struct gfx_object));
}
/* setup objects */
for(i=0;i<nums;i++)
{
/* dirty flag */
object_list->objects[i].dirty_flag = GFXOBJ_DIRTY_ALL;
/* link map */
object_list->objects[i].next = &object_list->objects[i+1];
}
/* setup object_list */
object_list->max_priority = max_priority;
object_list->nums = nums;
object_list->first_object = object_list->objects; /* top of link */
object_list->objects[nums-1].next = 0; /* bottom of link */
object_list->sort_type = GFXOBJ_SORT_DEFAULT;
/* resource tracking */
object_list->next = first_object_list;
first_object_list = object_list;
return object_list;
}
/* set pixel dirty flag */
void gfxobj_mark_all_pixels_dirty(struct gfx_object_list *object_list)
{
/* don't care , gfx object manager don't keep color remapped bitmap */
}
/* update object */
static void object_update(struct gfx_object *object)
{
int min_x,min_y,max_x,max_y;
/* clear dirty flag */
object->dirty_flag = 0;
/* if gfx == 0 ,then bypass (for special_handler ) */
if(object->gfx == 0)
return;
/* check visible area */
min_x = Machine->drv->visible_area.min_x;
max_x = Machine->drv->visible_area.max_x;
min_y = Machine->drv->visible_area.min_y;
max_y = Machine->drv->visible_area.max_y;
if(
(object->width==0) ||
(object->height==0) ||
(object->sx > max_x) ||
(object->sy > max_y) ||
(object->sx+object->width <= min_x) ||
(object->sy+object->height <= min_y) )
{ /* outside of visible area */
object->visible = 0;
return;
}
object->visible = 1;
/* set draw position with adjust source offset */
object->draw_x = object->sx -
( object->flipx ?
(object->gfx->width - (object->left + object->width)) : /* flip */
(object->left) /* non flip */
);
object->draw_y = object->sy -
( object->flipy ?
(object->gfx->height - (object->top + object->height)) : /* flip */
(object->top) /* non flip */
);
/* set clipping point to object draw area */
object->clip.min_x = object->sx;
object->clip.max_x = object->sx + object->width -1;
object->clip.min_y = object->sy;
object->clip.max_y = object->sy + object->height -1;
/* adjust clipping point with visible area */
if (object->clip.min_x < min_x) object->clip.min_x = min_x;
if (object->clip.max_x > max_x) object->clip.max_x = max_x;
if (object->clip.min_y < min_y) object->clip.min_y = min_y;
if (object->clip.max_y > max_y) object->clip.max_y = max_y;
}
/* update one of object list */
static void gfxobj_update_one(struct gfx_object_list *object_list)
{
struct gfx_object *object;
struct gfx_object *start_object,*last_object;
int dx,start_priority,end_priority;
int priorities = object_list->max_priority;
int priority;
if(object_list->sort_type&GFXOBJ_DO_SORT)
{
struct gfx_object *top_object[MAX_PRIORITY],*end_object[MAX_PRIORITY];
/* object sort direction */
if(object_list->sort_type&GFXOBJ_SORT_OBJECT_BACK)
{
start_object = object_list->objects + object_list->nums-1;
last_object = object_list->objects-1;
dx = -1;
}
else
{
start_object = object_list->objects;
last_object = object_list->objects + object_list->nums;
dx = 1;
}
/* reset each priority point */
for( priority = 0; priority < priorities; priority++ )
end_object[priority] = 0;
/* update and sort */
for(object=start_object ; object != last_object ; object+=dx)
{
/* update all objects */
if(object->dirty_flag)
object_update(object);
/* store link */
if(object->visible)
{
priority = object->priority;
if(end_object[priority])
end_object[priority]->next = object;
else
top_object[priority] = object;
end_object[priority] = object;
}
}
/* priority sort direction */
if(object_list->sort_type&GFXOBJ_SORT_PRIORITY_BACK)
{
start_priority = priorities-1;
end_priority = -1;
dx = -1;
}
else
{
start_priority = 0;
end_priority = priorities;
dx = 1;
}
/* link between priority */
last_object = 0;
for( priority = start_priority; priority != end_priority; priority+=dx )
{
if(end_object[priority])
{
if(last_object)
last_object->next = top_object[priority];
else
object_list->first_object = top_object[priority];
last_object = end_object[priority];
}
}
if(last_object == 0 )
object_list->first_object = 0;
else
last_object->next = 0;
}
else
{ /* non sort , update only linked object */
for(object=object_list->first_object ; object !=0 ; object=object->next)
{
/* update all objects */
if(object->dirty_flag)
object_update(object);
}
}
/* palette resource */
if(object->palette_flag)
{
/* !!!!! do not supported yet !!!!! */
}
}
void gfxobj_update(void)
{
struct gfx_object_list *object_list;
for(object_list=first_object_list ; object_list != 0 ; object_list=object_list->next)
gfxobj_update_one(object_list);
}
static void draw_object_one(struct osd_bitmap *bitmap,struct gfx_object *object)
{
if(object->special_handler)
{ /* special object , callback user draw handler */
object->special_handler(bitmap,object);
}
else
{ /* normaly gfx object */
drawgfx(bitmap,object->gfx,
object->code,
object->color,
object->flipx,
object->flipy,
object->draw_x,
object->draw_y,
&object->clip,
object->transparency,
object->transparet_color);
}
}
void gfxobj_draw(struct gfx_object_list *object_list)
{
struct osd_bitmap *bitmap = Machine->scrbitmap;
struct gfx_object *object;
for(object=object_list->first_object ; object ; object=object->next)
{
if(object->visible )
draw_object_one(bitmap,object);
}
}